/*
 * spi.h
 *
 *  Created on: Aug 3, 2013
 *      Author: Ken Arok
 *
 *
 * \brief Hardware Abstraction Layer of SPI Controller UC3C0512C
 *
 * Copyright (c) 2013 PT Hanindo Automation Solutions. All rights reserved.
 *
 */

#include "config_board.h"

#if BOARD_1_0_USED

#ifndef SPI_H_
#define SPI_H_

#include <stdint.h>
#include <stdbool.h>
#include <avr32/io.h>

#ifdef __cplusplus
extern "C" {
#endif

/** SPI Mode. */
#define SPI_MODE_0        0
#define SPI_MODE_1        1
#define SPI_MODE_2        2
#define SPI_MODE_3        3

/** \name SPI Status code.
 */
//! @{
#define SPI_STATUS_OK				0 //!< Success
#define SPI_ERR_IO_ERROR			1 //!< I/O error
#define SPI_ERR_FLUSHED				2 //!< Request flushed from queue
#define SPI_ERR_TIMEOUT				3 //!< Operation timed out
#define SPI_ERR_BAD_DATA			4 //!< Data integrity check failed
#define SPI_ERR_PROTOCOL			5 //!< Protocol error
#define SPI_ERR_UNSUPPORTED_DEV		6 //!< Unsupported device
#define SPI_ERR_NO_MEMORY			7 //!< Insufficient memory
#define SPI_ERR_INVALID_ARG			8 //!< Invalid argument
#define SPI_ERR_BAD_ADDRESS			9 //!< Bad address
#define SPI_ERR_BUSY				10 //!< Resource is busy
#define SPI_ERR_BAD_FORMAT			11 //!< Data format not recognized
#define SPI_OPERATION_IN_PROGRESS	128
//! @}

typedef uint8_t spi_status_code_t;

/** \name SPI Transfer mode.
 */
//! @{
#define SPI_POLLED_TX		1
#define SPI_POLLED_RX		2
#define SPI_INTERRUPT_TX	3
#define SPI_INTERRUPT_RX	4
//! @}

typedef uint8_t spi_transfer_mode_flag_t;

/* SPI path name */
typedef const char * SPI_path;

/* Structure of SPI peripheral decriptors. */
typedef struct {
	const char *path_name;	//!< Pointer to SPI path name
	uint8_t path_index;		//!< Index of path peripheral.
	uint8_t port_state;		//!< State of port (1 = open, 0 = close).
	uint32_t *recved_size;	//!< Actual received size for read operation.
	uint8_t transfer_mode;	//!< Transfer mode (bit 0: tx, bit 1: rx). 1 = interrupt; 0 = polled.
} spi_peripheral_descriptors_t;

/* SPI descriptor */
typedef void * spi_descriptor_t;


//! Option structure for SPI channels.
typedef struct {
	uint32_t baudrate;		//!< Preferred baudrate for the SPI.
	uint8_t bits;			//!< Number of bits in each character (8 to 16).
	uint8_t delay_bs;		//!< Delay before first clock pulse after selecting slave (in PBA clock periods).
	uint8_t delay_bct;		//!< Delay between each transfer/character (in PBA clock periods).
	uint8_t keep_actv;		//!< Sets this chip to keep active after last transfer to it.
	uint8_t spi_mode;		//!< Which SPI mode to use when transmitting.
	uint8_t modfdis;		//!< mode fault detection. With this bit cleared, the SPI
	bool master_setup;		//!< Setup for Master mode or Slave mode.
} spi_channel_options_t;


/** \brief Write packet data to SPI port.
 *  \param _descriptor				Pointer to peripheral descriptor.
 *  \param _pPacket					Pointer to data buffer want to be transmitted.
 *  \param _size_t					Number of byte/word to be transmitted.
 *
 * \return	SPI Status
 */
extern spi_status_code_t spi_write_word(spi_descriptor_t _descriptor, const void *_pPacket, uint32_t _size_t);

/** \brief Write packet data to SPI port.
 *  \param _descriptor				Pointer to peripheral descriptor.
 *  \param _pPacket					Pointer to data buffer want to be transmitted.
 *  \param _size_t					Number of byte/word to be transmitted.
 *
 * \return	SPI Status
 */
extern spi_status_code_t spi_write_byte(spi_descriptor_t _descriptor, const void *_pPacket, uint32_t _size_t);


/** \brief Read packet data from the port.
 *  \param _descriptor				Pointer to peripheral descriptor.
 *  \param _pRxBuff					Pointer to buffer where data will be stored.
 *  \param _size_t					Number of byte/word to be received.
 *
 * \return Status
 */
extern spi_status_code_t spi_read_word(spi_descriptor_t _descriptor, void *_pRxBuff, uint32_t _size_t);

/** \brief Read packet data from the port.
 *  \param _descriptor				Pointer to peripheral descriptor.
 *  \param _pRxBuff					Pointer to buffer where data will be stored.
 *  \param _size_t					Number of byte/word to be received.
 *
 * \return Status
 */
extern spi_status_code_t spi_read_byte(spi_descriptor_t _descriptor, void *_pRxBuff, uint32_t _size_t);


/** \brief Initialize SPI interface.
 */
extern void spi_init(void);


/** \brief Setting up SPI communication.
 *
 * \param _descriptor	Pointer to peripheral descriptor.
 * \param _opt			Pointer to SPI channel option parameter.
 *
 * \return SPI Status
 */
extern spi_status_code_t spi_setup(spi_descriptor_t _descriptor, const spi_channel_options_t *_opt);


/** \brief Set SPI transfer mode.
 *
 * \param _descriptor	Pointer to peripheral descriptor.
 * \param _flag			Mode flag.
 *						SPI_POLLED: TX = Polled, RX = Polled.
 *						SPI_POLEED_TX: TX = Polled, RX = Interrupt.
 *						SPI_POLLED_RX: TX = Interrupt, RX = Polled.
 *						SPI_INTERRUPT: TX = Interrupt, RX = Interrupt.
 *
 * \return SPI Status
 */
extern spi_status_code_t spi_tranfer_mode(spi_descriptor_t _descriptor, spi_transfer_mode_flag_t _flag);

/** \brief Select SPI Chip to be active.
 *
 * \param _descriptor	Pointer to peripheral descriptor.
 *
 * \return Status.
 */
extern spi_status_code_t spi_select_chip(spi_descriptor_t _descriptor);


/** \brief Deselect SPI Chip to be inactive.
 *
 * \param _descriptor	Pointer to peripheral descriptor.
 *
 * \return Status.
 */
extern spi_status_code_t spi_deselect_chip(spi_descriptor_t _descriptor);

/** \brief Open the SPI port.
 *
 * \param _path_name		Path name of SPI port.
 * \param _flag				Flag opening.
 *
 * \return Pointer to peripheral descriptor.
 */
extern spi_descriptor_t spi_open(SPI_path _path_name, const uint8_t _flag);

/** \brief Close the SPI port.
 *
 * \param _path_name		Pointer to peripheral descriptor.
 * \param _flag				Flag of closing.
 *
 * \return SPI Status
 */
extern spi_status_code_t spi_close(spi_descriptor_t _descriptor, const uint8_t _flag);


#ifdef __cplusplus
}
#endif


#endif /* SPI_H_ */

#endif /* BOARD_1_0_USED */
